home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 December / MACPOWER-1997-12.ISO.7z / MACPOWER-1997-12.ISO / AMUG / PROGRAMMING / Raven 1.2.sit / Raven 1.2 / • Extras • / SGI STL / stldebug.h < prev    next >
C/C++ Source or Header  |  1997-06-22  |  11KB  |  334 lines

  1. /*
  2.  *
  3.  * Copyright (c) 1997
  4.  * Moscow Center for SPARC Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute and sell this software
  7.  * and its documentation for any purpose is hereby granted without fee,
  8.  * provided that the above copyright notice appear in all copies and
  9.  * that both that copyright notice and this permission notice appear
  10.  * in supporting documentation.  Moscow Center for SPARC Technology makes no
  11.  * representations about the suitability of this software for any
  12.  * purpose.  It is provided "as is" without express or implied warranty.
  13.  *
  14.  */
  15. #ifndef __SGI_STL_STLDEBUG_H
  16. # define __SGI_STL_STLDEBUG_H
  17.  
  18. # if defined ( __STL_DEBUG )
  19. #include <ZDebug.h>                    // ・・・ハJDJ
  20.  
  21. # ifndef __SGI_STL_ITERATOR_H
  22. # include <iterator.h>
  23. # endif
  24. // stderr
  25. # include <stdio.h>
  26. # include <stdlib.h>
  27.  
  28. __BEGIN_STL_NAMESPACE
  29.  
  30. # define __STL_MSG_INVALID_ARGUMENT     "Invalid argument to operation (see operation documentation)"
  31.  
  32. # define __STL_MSG_INVALID_CONTAINER    "Taking an iterator out of destroyed (or otherwise corrupted) container"
  33. # define __STL_MSG_EMPTY_CONTAINER      "Trying to extract an object out from empty container"
  34. # define __STL_MSG_ERASE_PAST_THE_END   "Past-the-end iterator could not be erased"
  35. # define __STL_MSG_OUT_OF_BOUNDS        "Index out of bounds"
  36. # define __STL_MSG_NOT_OWNER            "Container doesn't own the iterator"
  37. # define __STL_MSG_INVALID_ITERATOR     "Uninitialized or invalidated (by mutating operation)"¥
  38.        " iterator used"
  39. # define __STL_MSG_INVALID_LEFTHAND_ITERATOR     "Uninitialized or invalidated (by mutating operation)"¥
  40.        " lefthand iterator in expression"
  41. # define __STL_MSG_INVALID_RIGHTHAND_ITERATOR     "Uninitialized or invalidated (by mutating operation)"¥
  42.        " righthand iterator in expression"
  43. # define __STL_MSG_DIFFERENT_OWNERS     "Iterators used in expression are from different owners"
  44. # define __STL_MSG_NOT_DEREFERENCEABLE  "Iterator could not be dereferenced (past-the-end ?)"
  45. # define __STL_MSG_INVALID_RANGE        "Range [first,last) is invalid"
  46. # define __STL_MSG_NOT_IN_RANGE_1       "Iterator is not in range [first,last)"
  47. # define __STL_MSG_NOT_IN_RANGE_2       "Range [first,last) is not in range [start,finish)"
  48. # define __STL_MSG_INVALID_ADVANCE      "The advance would produce invalid iterator"
  49.  
  50. #if RAVEN            // ・・・ハJDJ
  51.     #  define __stl_verbose_check(expr,diagnostic) ((expr) ? true : ¥
  52.     (DEBUGSTR("%s:%d STL error : %s¥n", __FILE__, __LINE__, diagnostic ),false))
  53.  
  54.     #  define __stl_verbose_return(expr,diagnostic) if (!(expr)) { ¥
  55.         DEBUGSTR("%s:%d STL error : %s¥n", __FILE__, __LINE__, diagnostic ); return false; }
  56. #else
  57.     #  define __stl_verbose_check(expr,diagnostic) ((expr) ? true : ¥
  58.     (fprintf(stderr, "%s:%d STL error : %s¥n", __FILE__, __LINE__, diagnostic ),false))
  59.  
  60.     #  define __stl_verbose_return(expr,diagnostic) if (!(expr)) { ¥
  61.         fprintf(stderr, "%s:%d STL error : %s¥n", __FILE__, __LINE__, diagnostic ); return false; }
  62. #endif
  63.  
  64. //============================================================================
  65.  
  66. template <class Iterator>
  67. bool __check_same_owner( const Iterator& i1, const Iterator& i2)
  68. {
  69.     __stl_verbose_return(i1.valid(), __STL_MSG_INVALID_LEFTHAND_ITERATOR);
  70.     __stl_verbose_return(i2.valid(), __STL_MSG_INVALID_RIGHTHAND_ITERATOR);
  71.     __stl_verbose_return(i1.owner()==i2.owner(), __STL_MSG_DIFFERENT_OWNERS);
  72.     return true;
  73. }
  74.  
  75. template <class Iterator>
  76. bool __check_if_owner( const void* owner, const Iterator& it)
  77. {
  78.     const void* owner_ptr = it.owner();
  79.     __stl_verbose_return(owner_ptr!=0, __STL_MSG_INVALID_ITERATOR);
  80.     __stl_verbose_return(owner==owner_ptr, __STL_MSG_NOT_OWNER);
  81.     return true;
  82. }
  83.  
  84. inline bool __check_bounds(int index, int size) 
  85. {
  86.     __stl_verbose_return(index<size, __STL_MSG_OUT_OF_BOUNDS);
  87.     return true;
  88. }
  89.  
  90. //=============================================================
  91.  
  92. template <class SafeIterator>
  93. inline bool  __dereferenceable(const SafeIterator& it) { 
  94.     return it.owner()->dereferenceable(it.get_iterator());
  95. }
  96.  
  97. template <class Iterator>
  98. inline bool __valid_range(const Iterator& i1 ,const Iterator& i2, 
  99.                           random_access_iterator_tag)
  100.     return i1<=i2;
  101. }
  102.  
  103. template <class Iterator>
  104. inline bool __valid_range(const Iterator& i1 ,const Iterator& i2, 
  105.                           bidirectional_iterator_tag)
  106.     // check if comparable
  107.     bool dummy(i1==i2);
  108.     return (dummy==dummy); 
  109. }
  110.  
  111. template <class Iterator>
  112. inline bool __valid_range(const Iterator& i1 ,const Iterator& i2, 
  113.                           forward_iterator_tag)
  114.     // check if comparable
  115.     bool dummy(i1==i2);
  116.     return (dummy==dummy); 
  117. }
  118.  
  119. template <class Iterator>
  120. inline bool __valid_range(const Iterator& i1 ,const Iterator& i2, 
  121.                           input_iterator_tag)
  122.     return false; 
  123. }
  124.  
  125. template <class Iterator>
  126. inline bool __valid_range(const Iterator& i1 ,const Iterator& i2, 
  127.                           output_iterator_tag)
  128.     return false; 
  129. }
  130.  
  131. template <class Iterator>
  132. inline bool __valid_range(const Iterator& i1, const Iterator& i2)
  133.     return __valid_range(i1,i2,iterator_category(i1));
  134. }
  135.  
  136. template <class Iterator>
  137. inline bool __in_range(const Iterator& it, const Iterator& i1, const Iterator& i2)
  138.     return __valid_range(i1,it,iterator_category(i1)) && 
  139.         __valid_range(it,i2,iterator_category(it));
  140. }
  141.  
  142. template <class Iterator>
  143. inline bool __in_range(const Iterator& first, const Iterator& last, 
  144.                        const Iterator& start, const Iterator& finish)
  145.     return __valid_range(first,last,iterator_category(first)) &&
  146.         __valid_range(start,first,iterator_category(first)) && 
  147.         __valid_range(last,finish,iterator_category(last));
  148. }
  149.  
  150. //=============================================================
  151.  
  152. template <class SafeIterator>
  153. bool  __check_dereferenceable(const SafeIterator& it) { 
  154.     __stl_verbose_return(it.valid(), __STL_MSG_INVALID_ITERATOR);
  155.     __stl_verbose_return(__dereferenceable(it), __STL_MSG_NOT_DEREFERENCEABLE);
  156.     return true;
  157. }
  158.  
  159. template <class SafeIterator, class Distance>
  160. bool __check_advance(const SafeIterator& it , Distance n )
  161.     __stl_verbose_return(it.valid(), __STL_MSG_INVALID_ITERATOR);
  162.     __stl_verbose_return(it.owner()->valid_advance(it.get_iterator(),n), 
  163.                          __STL_MSG_INVALID_ADVANCE);
  164.     return true;
  165. }
  166.  
  167. template <class Iterator>
  168. bool __check_range(const Iterator& first, const Iterator& last) {
  169.     __stl_verbose_return(__valid_range(first,last), __STL_MSG_INVALID_RANGE );
  170.     return true;
  171. }
  172.  
  173. template <class Iterator>
  174. bool __check_range(const Iterator& it, 
  175.                    const Iterator& start, const Iterator& finish) {
  176.     __stl_verbose_return(__in_range(it,start, finish), 
  177.                          __STL_MSG_NOT_IN_RANGE_1);
  178.     return true;
  179. }
  180.  
  181. template <class Iterator>
  182. bool __check_range(const Iterator& first, const Iterator& last, 
  183.                    const Iterator& start, const Iterator& finish) {
  184.     __stl_verbose_return(__in_range(first, last, start, finish), 
  185.                          __STL_MSG_NOT_IN_RANGE_2);
  186.     return true;
  187. }
  188. //===============================================================
  189.  
  190. // template <class Container>
  191. class __safe_base {
  192. protected:
  193.     typedef void* owner_ptr;
  194.     typedef __safe_base self;
  195.     typedef self* self_ptr;
  196. public:
  197.     __safe_base(const void* c) : 
  198.         owner_(owner_ptr(c)) {
  199.             attach();
  200.         }
  201.     const self* owner() const { return (const self*)owner_; }
  202.     bool  valid() const               { return owner()!=0; }
  203.     __safe_base(const self& rhs) : owner_(rhs.owner_) {
  204.         attach();
  205.     }
  206.     self& operator=(const self& rhs) {
  207.         if ( owner_ != rhs.owner_ ) {
  208.             detach();
  209.             owner_ = rhs.owner_;
  210.             attach();
  211.         }
  212.         return *this;
  213.     }
  214.     ~__safe_base() {
  215.         detach();
  216.         owner_  = 0;
  217.     }
  218.     void invalidate() { owner_=0; }
  219.     void attach() {
  220.         if (owner()) {
  221.             self* owner_node=(self*)owner();
  222.             __stl_verbose_assert(owner_node->owner()!=0, 
  223.                                  __STL_MSG_INVALID_CONTAINER);
  224.             self* list_begin = owner_node->next_;
  225.             next_=list_begin;
  226.             prev_ = list_begin->prev_;
  227.             (list_begin->prev_)->next_=this;
  228.             list_begin->prev_=this;
  229.         }   
  230.     }
  231.     void detach() {
  232.         if (owner()) {
  233.             prev_->next_ = next_ ;
  234.             next_->prev_ = prev_ ;
  235.             owner_=0;
  236.         }
  237.     }
  238.     self* prev() { return prev_; }
  239.     self* next() { return next_; }
  240.     void safe_init(const void* c) { 
  241.         owner_=owner_ptr(c); 
  242.         next_=prev_=this;
  243.     }
  244.     __safe_base() {}
  245.     // note : must be performed on roots
  246.     void swap_owners(self& x) {
  247.         owner_ptr tmp = owner_;
  248.         self* position;
  249.         for (position = x.next(); 
  250.              position!=&x; position=position->next()) {
  251.             position->owner_ = tmp;
  252.         }
  253.         tmp=x.owner_;
  254.         for (position = next(); 
  255.              position!=this; position=position->next()) {
  256.             position->owner_ = tmp;
  257.         }
  258.         x.owner_=owner_;
  259.         owner_=tmp;
  260.     }
  261.     void invalidate_all() {
  262.         for (__safe_base* position = next(); 
  263.              position!=this; position=position->next()) {
  264.             position->invalidate();
  265.         }
  266.         next_=prev_=this;;
  267.     }
  268.     mutable owner_ptr         owner_;
  269. protected:
  270.     mutable self_ptr          next_;
  271.     mutable self_ptr          prev_; 
  272. };
  273.  
  274. //============================================================
  275.  
  276. // _only_ for randomaccess iterators
  277. template <class Iterator, class SafeIterator>
  278. void __invalidate_range(__safe_base* base, 
  279.                         const Iterator& first,
  280.                         const Iterator& last, const SafeIterator&)
  281. {
  282.     typedef __safe_base* base_ptr;
  283.     typedef SafeIterator* safe_iterator_ptr;
  284.     base_ptr list_root = base;
  285.     for (base_ptr position = list_root->next(); 
  286.          position!=list_root;) {
  287.         if (__in_range(((safe_iterator_ptr)position)->get_iterator(),first,last)) {
  288.             base_ptr remove_position=position;
  289.             position=position->next();
  290.             remove_position->detach();
  291.         }
  292.         else
  293.             position=position->next();
  294.     }
  295. }
  296.  
  297. template <class Iterator, class SafeIterator>
  298. void __invalidate_iterator(__safe_base* base, 
  299.                            const Iterator& it, const SafeIterator&)
  300. {
  301.     typedef __safe_base* base_ptr;
  302.     typedef SafeIterator* safe_iterator_ptr;
  303.     base_ptr list_root = base;
  304.     for (base_ptr position = list_root->next(); 
  305.          position!=list_root;) {
  306.         if (((safe_iterator_ptr)position)->get_iterator()==it) {
  307.             base_ptr remove_position=position;
  308.             position=position->next();
  309.             remove_position->detach();
  310.         }
  311.         else
  312.             position=position->next();
  313.     }
  314. }
  315. //============================================================
  316.  
  317. __END_STL_NAMESPACE
  318.  
  319. # endif /* __STL_DEBUG */
  320.  
  321. #endif
  322.  
  323.  
  324.  
  325.